package pers.mihao.quickstream.publish.strategy.filter.factory;

import pers.mihao.quickstream.common.util.CollectionUtil;
import pers.mihao.quickstream.publish.strategy.context.ChooseContext;
import pers.mihao.quickstream.publish.strategy.dto.ChooseAccount;
import pers.mihao.quickstream.publish.strategy.dto.ChooseAccountScore;
import pers.mihao.quickstream.publish.strategy.filter.AccountFilter;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author mihao
 * @since 2024/11/25
 */
public class DefaultAccountFilterFactory implements AccountFilterFactory {

    List<AccountFilter> accountFilters;

    public DefaultAccountFilterFactory(List<AccountFilter> accountFilters) {
        this.accountFilters = accountFilters;
    }

    @Override
    public AccountFilter buildFilterChain(ChooseContext chooseContext) {
        AccountFilterChain pre = new AccountFilterChain(), _pre = pre;
        for (AccountFilter filter : accountFilters) {
            if (!filter.isMatch(chooseContext)) {
                continue;
            }
            AccountFilterChain chain = new AccountFilterChain();
            chain.curr = filter;
            pre.next = chain;
            pre = chain;
        }
        return _pre.next;
    }

    private static class AccountFilterChain implements AccountFilter {
        AccountFilter curr;
        AccountFilter next;

        @Override
        public List<ChooseAccount> accountFilter(ChooseContext chooseContext, List<ChooseAccountScore> accountScores) {
            List<ChooseAccount> chooseAccounts = curr.accountFilter(chooseContext, accountScores);
            if (CollectionUtil.isEmpty(chooseAccounts)) {
                return new ArrayList<>();
            }
            if (next == null) {
                return chooseAccounts;
            }
            Set<Long> account = chooseAccounts.stream().map(ChooseAccount::getAccountId).collect(Collectors.toSet());
            List<ChooseAccountScore> filterAccount = accountScores.stream()
                    .filter(a -> account.contains(a.getChooseAccount().getAccountId())).collect(Collectors.toList());
            return next.accountFilter(chooseContext, filterAccount);
        }
    }
}
